#pragma once

#include <vector>
#include <atomic>

namespace minidb
{

class Arena
{
public:
    Arena();
    
    Arena(const Arena &) = delete;
    Arena &operator=(const Arena &) = delete;

    // Return a pointer to a newly allocated memory block of "bytes" bytes.
    char *Allocate(size_t bytes);

    // Allocate memory with the normal alignment guarantees provided by malloc.
    char *AllocateAligned(size_t bytes);

    // Returns an estimate of the total memory usage of data allocated
    // by the arena.
    size_t MemoryUsage() const
    {
        // note: memory_order_relaxed 只保证原子操作，不保证任何顺序，性能最高。适合在操作不存在先后顺序时使用
        return memory_usage_.load(std::memory_order_relaxed);
    }

    ~Arena();

private:
    /// @brief 分配bytes字节块,返回分配的块首地址
    /// @param bytes 
    /// @return 
    char* AllocateNewBlock(std::size_t bytes);

    /// @brief 剩余字节不足时重新分配块. bytes > KBlockSize/4分配大小为 bytes 的块. bytes <= KBlockSize/4 时分配KBlockSize的块
    /// @param bytes 
    /// @return 
    char* AllocateFallback(std::size_t bytes);

private:
    std::vector<char *> blocks_;
    size_t alloc_bytes_remaining_;
    std::atomic<std::size_t> memory_usage_;
    char *alloc_ptr_;
};

} // namespace minidb